#!/bin/bash

#切换到脚本所在目录并保存绝对路径
cd $(dirname "$0")
SELFDIR=`pwd`

#ubuntu、debian、deepin、mint
OSNAME="ubuntu"
CHECK_NAME=`cat /etc/os-release | grep -E '^NAME=.*CentOS|^NAME=.*RedHat'`

if [ -n "$CHECK_NAME" ] ; then
    OSNAME="centos"
fi

CHECK_NAME=`cat /etc/os-release | grep -E '^NAME=.*Arch|^NAME=.*Manjaro'`

if [ -n "$CHECK_NAME" ] ; then
    OSNAME="arch"
fi

SUDO="sudo"

if [ "$UID" -eq 0 ] ; then
    SUDO=''
fi

if [ -z `which curl` ] ; then
    if [ $OSNAME = "ubuntu" ] ; then
        $SUDO apt install curl -y
    elif [ $OSNAME = "centos" ] ; then
        $SUDO yum install curl -y
    else
        $SUDO pacman -Sy curl --noconfirm
    fi
fi

INSTALL_DIR=/usr/local/mno

DOWNLOAD_DIR="$SELFDIR/versions"
SHASUM_DIR="shasum"

INSTALL_FORCE=0
INSTALL_RESET=0
REPLACE_VERSION=0
LOCAL_INSTALL=0

ORG_URL='https://nodejs.org/dist'
URL='https://cdn.npmmirror.com/binaries/node'

#SHASUM256.txt
ORG_SHA256SUM_URL='https://nodejs.org/dist'
SHA256SUM_URL='https://cdn.npmmirror.com/binaries/node'
SHA256_URL_FILE='SHASUMS256.txt.asc'

MAIN_VERSION='v24.x v22.x'

#2022:18 2023:20 2024:22 2025:24
YEAR=`date '+%Y'`
MONTH=`date '+%m'`

case $YEAR in
    2023)
        MAIN_VERSION='v18.x v16.x v14.x'
        ;;
    2024)
        MAIN_VERSION='v20.x v18.x v16.x'
        ;;
    2025)
        MAIN_VERSION='v22.x v20.x v18.x'
        ;;
    2026)
        MAIN_VERSION='v24.x v22.x v20.x'
        ;;
    2027)
        MAIN_VERSION='v26.x v24.x v22.x'
        ;;
    2028)
        MAIN_VERSION='v28.x v26.x v24.x'
        ;;
    2029)
        MAIN_VERSION='v30.x v28.x v26.x v24.x'
        ;;
esac


if [ "$MONTH" -gt 4 ] ; then
    case $YEAR in
        2022)
            MAIN_VERSION='v18.x v16.x v14.x'
            ;;
        2023)
            MAIN_VERSION='v20.x v18.x v16.x'
            ;;
        2024)
            MAIN_VERSION='v22.x v20.x v18.x'
            ;;
        2025)
            MAIN_VERSION='v24.x v22.x v20.x'
            ;;
        2026)
            MAIN_VERSION='v26.x v24.x v22.x'
            ;;
        2027)
            MAIN_VERSION='v28.x v26.x v24.x'
            ;;
        2028)
            MAIN_VERSION='v30.x v28.x v26.x'
            ;;
        2029)
            MAIN_VERSION='v32.x v30.x v28.x'
            ;;
    esac
fi

VERSIONS=''

USER_VERSIONS=''

LATEST_INFO=''

SYS_ARCH='x64'

. "$SELFDIR/arch.sh"

get_latest () {
    LATEST_INFO=`curl -k -s "$SHA256SUM_URL/latest-$1/SHASUMS256.txt" | grep "node-v.*linux-$SYS_ARCH.tar.xz"`
}

_LATEST_TMP_SHA=''
_LATEST_TMP_NAME=''
_LATEST_TMP_VERSION=''

parse_latest_sha () {
    _LATEST_TMP_SHA=`echo $1 | awk -F ' ' '{printf $1}'`
}

parse_latest_name () {
    _LATEST_TMP_NAME=`echo $1 | awk -F ' ' '{printf $2}'`
}

parse_latest_version () {
    _LATEST_TMP_VERSION=`echo $1 | awk -F '-' '{printf $2}'`
}

try_get_latest_list () {
    for a in $MAIN_VERSION ; do
        get_latest $a

        if [ "$?" -ne 0 ] ; then
            continue
        fi

        parse_latest_sha "$LATEST_INFO"
        parse_latest_name "$LATEST_INFO"
        parse_latest_version $_LATEST_TMP_NAME

        echo $_LATEST_TMP_SHA > $SHASUM_DIR/$_LATEST_TMP_VERSION

        VERSIONS="$VERSIONS $_LATEST_TMP_VERSION"
    done
}

help() {
    echo "install.sh [OPTIONS]"
    echo "OPTIONS: -f | -r | -v | -h | [VERSION]"
    echo "  -f 强制安装，如果检测到冲突则会删除已有。"
    echo "  -r 覆盖安装，检测到已经安装的目录，则会先删除。"
    echo "  -v 使用指定的版本，默认如果添加版本则会扩充，使用此选项表示不安装默认的。"
    echo "  -h 显示帮助信息。"
    echo "  -l 显示默认安装的版本。"
    echo "  --local 使用本地版本，会在versions目录中找对应的版本。"
    echo "  --org 使用Node.js官方的URL。"
}


LINK_NAME='node npm npx'
LINK_DIR='/usr/local/bin'
LINK_DIR2='/usr/bin'

install_cmd() {
    #如果自己已经在安装目录则不操作
    if [ "$SELFDIR" != "$INSTALL_DIR" ] ; then
        $SUDO cp $SELFDIR/mno $LINK_DIR/mno
        $SUDO chmod +x $LINK_DIR/mno

        $SUDO cp $SELFDIR/install.sh $INSTALL_DIR/
        $SUDO chmod +x $INSTALL_DIR/install.sh

        $SUDO cp $SELFDIR/arch.sh $INSTALL_DIR/
        $SUDO cp $SELFDIR/autoclear.js $INSTALL_DIR/
    fi
}

SHOW_VERSION=0
NO_DEFAULT=0

TEST_MODE=0

if [ "$#" -gt 0 ] ; then
    for a in $@ ; do
        if [ "$a" = "-f" ] ; then
            INSTALL_FORCE=1
        elif [ "$a" = "-r" ] ; then
            INSTALL_RESET=1
        elif [ "$a" = "-v" ] ; then
            REPLACE_VERSION=1
        elif [ "$a" = "--org" ] ; then
            URL="$ORG_URL"
            SHA256SUM_URL="$ORG_SHA256SUM_URL"
        elif [ "$a" = "-l" ] ; then
            SHOW_VERSION=1
        elif [ "$a" = "--no-default" ] ; then
            NO_DEFAULT=1
        elif [ "$a" = "-h" ] ; then
            help
            exit 0
        elif [ "$a" = "-u" ] ; then
            install_cmd
            exit $?
        elif [ "$a" = "--local" ] ; then
            LOCAL_INSTALL=1
        elif [ "$a" = "--test" ] ; then
            TEST_MODE=1
        elif [ "$a" = "-rf" ] ; then
            INSTALL_FORCE=1
            INSTALL_RESET=1
        elif [ "${a:0:1}" = "v" ] ; then
            #认为是要添加的版本
            if [ "${#a}" -gt 5 ] ; then
                USER_VERSIONS="$USER_VERSIONS $a"
            fi
        elif [ "${#a}" -gt 4 ] ; then
            USER_VERSIONS="$USER_VERSIONS v$a"
        fi
    done
fi

if [ ! -d "$DOWNLOAD_DIR" ] ; then
    mkdir $DOWNLOAD_DIR
fi

#创建SHASUM_DIR
if [ ! -d "$SHASUM_DIR" ] ; then
    mkdir $SHASUM_DIR
fi

check_filename () {
    __N__=`echo "$1" | grep "node-v.*linux-$SYS_ARCH\.tar\.xz"`

    if [ -z "$__N__" ] ; then
        return 1
    fi

    return 0
}

if [ "$LOCAL_INSTALL" -eq 0 ] ; then
    try_get_latest_list
else
    TMPLIST=`ls $DOWNLOAD_DIR | sort -r`

    for a in $TMPLIST ; do
        if check_filename $a ; then
            parse_latest_version $a
            VERSIONS="$VERSIONS $_LATEST_TMP_VERSION"
        fi
    done
fi

#如果是替换版本则进行赋值，否则扩充。
if [ "$REPLACE_VERSION" = 1 ] ; then
    VERSIONS=$USER_VERSIONS
else
    VERSIONS="$VERSIONS $USER_VERSIONS"
fi

if [ "$SHOW_VERSION" -eq 1 ] ; then
    for vn in $VERSIONS ; do
        echo $vn
    done

    exit 0
fi


echo "Prepare to install $VERSIONS"
echo ''

if [ ! -d "$INSTALL_DIR" ] ; then
    echo "正在创建安装目录..."
    $SUDO mkdir $INSTALL_DIR
fi

# 获取并保存版本的校验信息

get_and_save_sha256sum () {
    FULL_SHA_URL="$SHA256SUM_URL/$1/$SHA256_URL_FILE"

    curl -k -s $FULL_SHA_URL | grep "linux-$SYS_ARCH\.tar\.xz" | awk -F ' ' '{printf $1}' > $SELFDIR/$SHASUM_DIR/$1

}

OK_VERSION=''

TMP_URL=''
TMP_FNAME=''
TMP_DNAME=''

download_url() {
    TMP_URL="$URL/$1/node-$1-linux-$SYS_ARCH.tar.xz"
}

make_filename () {
    TMP_FNAME="node-$1-linux-$SYS_ARCH.tar.xz"
}

make_tar_dirname () {
    TMP_DNAME="node-$1-linux-$SYS_ARCH"
}

#$1 version ; $2 filename

file_sha256_sum () {

    SHASUM=`sha256sum "$DOWNLOAD_DIR/$2" | awk -F ' ' '{printf $1}'`

    SHASUMTRUE=`cat $SELFDIR/$SHASUM_DIR/$1`

    #echo '--' $SHASUM
    #echo '--' $SHASUMTRUE

    if [ "$SHASUM" = "$SHASUMTRUE" ] ; then
        return 0
    fi

    return 1
}

#start install

clear_install_lock () {
    if [ -f "/tmp/mno-install-lock" ] ; then
        rm /tmp/mno-install-lock
    fi
}

FLAG_CLEAR_LOCK=1

clear_and_exit () {
    __EXIT_CODE__=$?
    if [ "$FLAG_CLEAR_LOCK" -eq 1 ] ; then
        clear_install_lock
    fi
    exit $__EXIT_CODE__
}

trap clear_and_exit INT TERM EXIT

if [ -f "/tmp/mno-install-lock" ] ; then
    FLAG_CLEAR_LOCK=0
    echo "安装程序正在进行，请勿多次运行"
    printf "如果确保没有执行mno update 或 install.sh，\n请运行 rm /tmp/mno-install-lock 然后再次安装。\n"
    printf "如果遇到权限问题，你可能需要使用$SUDO rm /tmp/mno-install-lock"
    exit 0
else
    touch /tmp/mno-install-lock
fi

if [ "$TEST_MODE" -eq 1 ] ; then
    echo 'test install(60s)...' && echo 'run mno install in other terminal' && sleep 60 && echo 'test install end'
    exit 0
fi

cd $DOWNLOAD_DIR

FAILED_DOWNLOAD=''

for n in $VERSIONS ; do

    if [ "$INSTALL_RESET" -eq 0 ] ; then
        make_tar_dirname $n
        if [ -d "$INSTALL_DIR/$TMP_DNAME" ] ; then
            echo "$n 已经安装"
            continue
        fi
    fi

    if [ -f "$SELFDIR/$SHASUM_DIR/$n" ] ; then
        TMP_SHASUM=`cat $SELFDIR/shasum/$n`
        if [ -z "$TMP_SHASUM" ] ; then
            rm "$SELFDIR/$SHASUM_DIR/$n"
        fi
    fi

    # 检测sha256校验文件是否存在
    if [ ! -f "$SELFDIR/$SHASUM_DIR/$n" ] ; then
        echo "验证SHA(try to get $n sha256sum)..."
        if get_and_save_sha256sum $n ; then
            echo "$n sha256sum ok."
        else
            echo "get $n sha256sum failed!"
            continue
        fi
    fi
    
    download_url $n
    
    make_filename $n

    if [ -f "$TMP_FNAME" ] ; then
        if file_sha256_sum $n $TMP_FNAME ; then
            OK_VERSION="$OK_VERSION $n"
            continue
        else
            echo '删除已存在版本'
            rm $TMP_FNAME
        fi
    fi 

    echo "下载 $TMP_FNAME（downloading $TMP_FNAME）"

    curl $TMP_URL -o $TMP_FNAME
    
    # 下载失败
    if [ "$?" -ne 0 ] ; then
        if [ -f "$TMP_FNAME" ] ; then
            rm $TMP_FNAME
        fi
    else
        if file_sha256_sum $n $TMP_FNAME ; then
            OK_VERSION="$OK_VERSION $n"
        else
            echo "$TMP_FNAME 下载失败，请稍候再试！[Error: download failed, please try again]"
            FAILED_DOWNLOAD="$FAILED_DOWNLOAD $n"
        fi
    fi
done


DEFAULT_NODE=0

cd $SELFDIR

for n in $OK_VERSION ; do
    
    make_tar_dirname $n
    make_filename $n

    echo "安装 $TMP_FNAME [Installing $TMP_FNAME]..."

    #如果是重置模式，则检测目录存在先删除再解压
    if [ "$INSTALL_RESET" -eq 1 ] ; then
        if [ -a "$INSTALL_DIR/$TMP_DNAME" ] ; then
            $SUDO rm -rf "$INSTALL_DIR/$TMP_DNAME"
        fi
    fi

    if [ ! -d "$INSTALL_DIR/$TMP_DNAME" ] ; then
        $SUDO tar -C $INSTALL_DIR -xf $DOWNLOAD_DIR/$TMP_FNAME
        # tar 解压后，不会因为sudo就改变用户的身份
        if [ "$UID" -eq 0 ] ; then
            $SUDO chown root:root -R $INSTALL_DIR/$TMP_DNAME
        fi
    else
        echo "目录 $TMP_DNAME 已经存在"
    fi

    if [ $NO_DEFAULT -gt 0 ] ; then
        continue
    fi

    if [ "$DEFAULT_NODE" -eq 0 ] ; then
        for m in $LINK_NAME ; do
            if [ -L "$LINK_DIR/$m" ] ; then
                $SUDO rm "$LINK_DIR/$m"
            elif [ -a "$LINK_DIR/$m" ] ; then
                if [ "$INSTALL_FORCE" -eq 0 ] ; then
                    echo "$LINK_DIR/$m 不是一个链接文件，将不会被删除，请确认是否已经安装了node，或者使用-f参数强制安装"
                    continue
                else
                    $SUDO rm -rf "$LINK_DIR/$m"
                fi
            fi

            $SUDO ln -s "$INSTALL_DIR/$TMP_DNAME/bin/$m" "$LINK_DIR/$m"
            if [ ! -f "$LINK_DIR2/$m" ] ; then
                $SUDO ln -s "$INSTALL_DIR/$TMP_DNAME/bin/$m" "$LINK_DIR2/$m"
            else
                if [ "$INSTALL_FORCE" -ne 0 ] ; then
                    $SUDO rm -rf "$LINK_DIR2/$m"
                    $SUDO ln -s "$INSTALL_DIR/$TMP_DNAME/bin/$m" "$LINK_DIR2/$m"
                fi
            fi
        done

        DEFAULT_NODE=1
    fi

done

if [ -n "$FAILED_DOWNLOAD" ] ; then
    echo "以下版本下载失败，请检查网络情况或检查是否为正式发布的版本并重试"
    for n in $FAILED_DOWNLOAD ; do
        echo $n
    done
fi

if [ -z "$OK_VERSION" ] ; then
    echo "没有新版本被安装，或者已经是最新版本"
    exit 1
fi

install_cmd

echo "OK"

